// ThreadSafeQueue_test.cpp
#include <gtest/gtest.h>
#include <thread>
#include <chrono>
#include <atomic>
#include <vector>
#include <string>
#include <algorithm>
#include "base/ThreadSafeQueue.hpp"

using namespace cytoolkit;
using namespace std::chrono_literals;

class ThreadSafeQueueTest : public ::testing::Test {
protected:
    void SetUp() override {
        // 每个测试前重置队列
        queue = std::make_unique<ThreadSafeQueue<int>>();
    }

    void TearDown() override {
        queue.reset();
    }

    std::unique_ptr<ThreadSafeQueue<int>> queue;
};

// ==================== 基础功能测试 ====================

TEST_F(ThreadSafeQueueTest, PushAndPop) {
    // 测试基本的push和pop功能
    EXPECT_TRUE(queue->push(1));
    EXPECT_TRUE(queue->push(2));
    EXPECT_TRUE(queue->push(3));
    
    EXPECT_EQ(queue->size(), 3);
    EXPECT_FALSE(queue->empty());
    
    auto value = queue->tryPop();
    EXPECT_TRUE(value.has_value());
    EXPECT_EQ(value.value(), 1);
    
    EXPECT_EQ(queue->pop(), 2);
    EXPECT_EQ(queue->tryPop().value(), 3);
    EXPECT_TRUE(queue->empty());
}

TEST_F(ThreadSafeQueueTest, Emplace) {
    // 测试原地构造功能
    struct TestStruct {
        int a;
        double b;
        std::string c;
        TestStruct(int a, double b, std::string c) : a(a), b(b), c(c) {}
    };
    
    ThreadSafeQueue<TestStruct> structQueue;
    EXPECT_TRUE(structQueue.emplace(1, 2.0, "test"));
    
    auto result = structQueue.tryPop();
    EXPECT_TRUE(result.has_value());
    EXPECT_EQ(result->a, 1);
    EXPECT_EQ(result->b, 2.0);
    EXPECT_EQ(result->c, "test");
}

TEST_F(ThreadSafeQueueTest, MoveSemantics) {
    // 测试移动语义 - 使用字符串队列
    ThreadSafeQueue<std::string> stringQueue;
    std::string original = "hello";
    stringQueue.push(std::move(original));
    
    auto value = stringQueue.pop();
    EXPECT_EQ(value, "hello");
    // 注意：original 被移动后状态未定义，不检查其内容
}

TEST_F(ThreadSafeQueueTest, MoveSemanticsWithInt) {
    // 测试整数的移动语义（虽然整数移动就是拷贝）
    queue->push(42);
    auto value = queue->pop();
    EXPECT_EQ(value, 42);
}

TEST_F(ThreadSafeQueueTest, FrontAndBack) {
    // 测试查看头尾元素功能
    queue->push(10);
    queue->push(20);
    queue->push(30);
    
    EXPECT_EQ(queue->front(), 10);
    EXPECT_EQ(queue->back(), 30);
    
    queue->pop(); // 移除10
    EXPECT_EQ(queue->front(), 20);
    EXPECT_EQ(queue->back(), 30);
}

// ==================== 容量限制测试 ====================

TEST_F(ThreadSafeQueueTest, CapacityLimit) {
    ThreadSafeQueue<int> limitedQueue(2); // 容量为2
    
    EXPECT_TRUE(limitedQueue.push(1));
    EXPECT_TRUE(limitedQueue.push(2));
    EXPECT_FALSE(limitedQueue.push(3)); // 应该失败
    
    EXPECT_TRUE(limitedQueue.full());
    EXPECT_EQ(limitedQueue.size(), 2);
    
    limitedQueue.pop(); // 移除一个元素
    EXPECT_FALSE(limitedQueue.full());
    EXPECT_TRUE(limitedQueue.push(3)); // 现在应该成功
}

TEST_F(ThreadSafeQueueTest, PushWaitWithCapacity) {
    ThreadSafeQueue<int> limitedQueue(1); // 容量为1
    
    std::atomic<bool> pushCompleted{false};
    std::atomic<bool> secondPushStarted{false};
    
    std::thread producer([&]() {
        limitedQueue.pushWait(1); // 应该立即成功
        pushCompleted = true;
        secondPushStarted = true;
        limitedQueue.pushWait(2); // 应该阻塞直到有消费者
    });
    
    // 等待第一次push完成
    while (!pushCompleted) {
        std::this_thread::sleep_for(1ms);
    }
    EXPECT_TRUE(pushCompleted);
    
    // 确保第二次push已经开始（应该被阻塞）
    while (!secondPushStarted) {
        std::this_thread::sleep_for(1ms);
    }
    std::this_thread::sleep_for(10ms); // 给点时间让生产者阻塞
    
    // 取出元素，让生产者继续
    auto value = limitedQueue.tryPop();
    EXPECT_TRUE(value.has_value());
    EXPECT_EQ(value.value(), 1);
    
    producer.join(); // 确保生产者线程完成
}

// ==================== 超时操作测试 ====================

TEST_F(ThreadSafeQueueTest, PushTimeout) {
    ThreadSafeQueue<int> limitedQueue(1);
    limitedQueue.push(1); // 队列已满
    
    auto start = std::chrono::steady_clock::now();
    bool result = limitedQueue.pushTimeout(2, 50ms); // 应该超时
    auto end = std::chrono::steady_clock::now();
    
    EXPECT_FALSE(result);
    auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
    EXPECT_GE(duration.count(), 45); // 允许一些误差
}

TEST_F(ThreadSafeQueueTest, PopTimeout) {
    auto start = std::chrono::steady_clock::now();
    auto result = queue->popTimeout(30ms);
    auto end = std::chrono::steady_clock::now();
    
    EXPECT_FALSE(result.has_value());
    auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
    EXPECT_GE(duration.count(), 25); // 允许一些误差
}

TEST_F(ThreadSafeQueueTest, PopTimeoutWithData) {
    queue->push(42);
    
    auto start = std::chrono::steady_clock::now();
    auto result = queue->popTimeout(100ms);
    auto end = std::chrono::steady_clock::now();
    
    EXPECT_TRUE(result.has_value());
    EXPECT_EQ(result.value(), 42);
    
    auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
    EXPECT_LT(duration.count(), 50); // 应该立即返回
}

// ==================== 批量操作测试 ====================

TEST_F(ThreadSafeQueueTest, PushRange) {
    std::vector<int> data = {1, 2, 3, 4, 5};
    
    size_t pushed = queue->pushRange(data.begin(), data.end());
    EXPECT_EQ(pushed, 5);
    EXPECT_EQ(queue->size(), 5);
    
    // 测试容量限制下的批量push
    ThreadSafeQueue<int> limitedQueue(3);
    pushed = limitedQueue.pushRange(data.begin(), data.end());
    EXPECT_EQ(pushed, 3);
    EXPECT_EQ(limitedQueue.size(), 3);
}

TEST_F(ThreadSafeQueueTest, PopBulk) {
    // 准备测试数据
    for (int i = 1; i <= 10; ++i) {
        queue->push(i);
    }
    
    auto result = queue->popBulk(5); // 取出5个元素
    EXPECT_EQ(result.size(), 5);
    EXPECT_EQ(queue->size(), 5);
    
    for (size_t i = 0; i < result.size(); ++i) {
        EXPECT_EQ(result[i], static_cast<int>(i + 1));
    }
    
    // 取出剩余元素
    result = queue->popBulk(10); // 请求10个，但只有5个可用
    EXPECT_EQ(result.size(), 5);
    for (size_t i = 0; i < result.size(); ++i) {
        EXPECT_EQ(result[i], static_cast<int>(i + 6));
    }
    
    EXPECT_TRUE(queue->empty());
}

TEST_F(ThreadSafeQueueTest, PopBulkEmptyQueue) {
    std::atomic<bool> consumerStarted{false};
    std::atomic<bool> consumerFinished{false};
    
    std::thread consumer([this, &consumerStarted, &consumerFinished]() {
        consumerStarted = true;
        auto result = queue->popBulk(); // 应该阻塞
        EXPECT_TRUE(result.empty()); // 队列关闭时返回空
        consumerFinished = true;
    });
    
    // 等待消费者线程启动
    while (!consumerStarted) {
        std::this_thread::sleep_for(1ms);
    }
    std::this_thread::sleep_for(10ms); // 确保消费者已经阻塞
    
    queue->shutdown(); // 关闭队列唤醒消费者
    consumer.join();
    EXPECT_TRUE(consumerFinished);
}

// ==================== 队列管理测试 ====================

TEST_F(ThreadSafeQueueTest, Drain) {
    for (int i = 0; i < 5; ++i) {
        queue->push(i);
    }
    
    auto drained = queue->drain();
    EXPECT_EQ(drained.size(), 5);
    EXPECT_TRUE(queue->empty());
    
    for (int i = 0; i < 5; ++i) {
        EXPECT_EQ(drained[i], i);
    }
}

TEST_F(ThreadSafeQueueTest, Clear) {
    for (int i = 0; i < 5; ++i) {
        queue->push(i);
    }
    
    queue->clear();
    EXPECT_TRUE(queue->empty());
    EXPECT_FALSE(queue->tryPop().has_value());
}

TEST_F(ThreadSafeQueueTest, ShutdownAndRestart) {
    EXPECT_FALSE(queue->isShutdown());
    
    queue->shutdown();
    EXPECT_TRUE(queue->isShutdown());
    
    EXPECT_TRUE(queue->push(1));
    
    
    // 重启队列
    queue->restart();
    EXPECT_EQ(queue->size(), 1);
    EXPECT_TRUE(queue->tryPop().has_value());
    EXPECT_FALSE(queue->isShutdown());
    
    // 重启后应该正常工作
    EXPECT_TRUE(queue->push(1));
    EXPECT_TRUE(queue->tryPop().has_value());
}

TEST_F(ThreadSafeQueueTest, PopAfterShutdown) {
    // 先放入一些数据
    queue->push(1);
    queue->push(2);
    
    queue->shutdown();
    
    // 关闭后应该还能取出剩余数据
    EXPECT_EQ(queue->pop(), 1);
    EXPECT_EQ(queue->pop(), 2);
    
    // 数据取完后，pop应该抛出异常
    EXPECT_THROW(queue->pop(), std::runtime_error);
}

// ==================== 多线程并发测试 ====================

TEST_F(ThreadSafeQueueTest, ProducerConsumer) {
    const int numItems = 100;
    std::atomic<int> consumedCount{0};
    std::atomic<int> producedCount{0};
    
    std::thread producer([this, &producedCount]() {
        for (int i = 0; i < numItems; ++i) {
            if (queue->push(i)) {
                ++producedCount;
            }
        }
    });
    
    std::thread consumer([&]() {
        for (int i = 0; i < numItems; ++i) {
            int value = queue->pop();
            EXPECT_EQ(value, i); // 保证顺序
            ++consumedCount;
        }
    });
    
    producer.join();
    consumer.join();
    
    EXPECT_EQ(consumedCount, numItems);
    EXPECT_EQ(producedCount, numItems);
    EXPECT_TRUE(queue->empty());
}

TEST_F(ThreadSafeQueueTest, MultipleProducers) {
    const int numProducers = 4;
    const int itemsPerProducer = 25;
    const int totalItems = numProducers * itemsPerProducer;
    
    std::vector<std::thread> producers;
    std::atomic<int> producedCount{0};
    
    for (int i = 0; i < numProducers; ++i) {
        producers.emplace_back([this, i, itemsPerProducer, &producedCount]() {
            for (int j = 0; j < itemsPerProducer; ++j) {
                if (queue->push(i * itemsPerProducer + j)) {
                    ++producedCount;
                }
            }
        });
    }
    
    std::atomic<int> consumedCount{0};
    std::thread consumer([&]() {
        std::vector<int> receivedValues;
        for (int i = 0; i < totalItems; ++i) {
            int value = queue->pop();
            receivedValues.push_back(value);
            ++consumedCount;
        }
        
        // 验证收到了所有值（顺序可能打乱）
        std::sort(receivedValues.begin(), receivedValues.end());
        for (int i = 0; i < totalItems; ++i) {
            EXPECT_EQ(receivedValues[i], i);
        }
    });
    
    for (auto& producer : producers) {
        producer.join();
    }
    consumer.join();
    
    EXPECT_EQ(producedCount, totalItems);
    EXPECT_EQ(consumedCount, totalItems);
}

TEST_F(ThreadSafeQueueTest, MultipleConsumers) {
    const int numConsumers = 4;
    const int totalItems = 100;
    
    // 先生产所有数据
    for (int i = 0; i < totalItems; ++i) {
        queue->push(i);
    }
    
    std::vector<std::thread> consumers;
    std::atomic<int> consumedCount{0};
    std::mutex mutex;
    std::vector<int> consumedValues;
    
    for (int i = 0; i < numConsumers; ++i) {
        consumers.emplace_back([&]() {
            while (consumedCount < totalItems) {
                auto value = queue->tryPop();
                if (value.has_value()) {
                    std::lock_guard lock(mutex);
                    consumedValues.push_back(value.value());
                    ++consumedCount;
                } else {
                    std::this_thread::sleep_for(1ms);
                }
            }
        });
    }
    
    for (auto& consumer : consumers) {
        consumer.join();
    }
    
    EXPECT_EQ(consumedCount, totalItems);
    
    // 验证所有值都被消费了（顺序可能打乱）
    std::sort(consumedValues.begin(), consumedValues.end());
    for (int i = 0; i < totalItems; ++i) {
        EXPECT_EQ(consumedValues[i], i);
    }
}

// ==================== 边界条件测试 ====================

TEST_F(ThreadSafeQueueTest, EmptyQueueOperations) {
    EXPECT_TRUE(queue->empty());
    EXPECT_FALSE(queue->tryPop().has_value());
    EXPECT_FALSE(queue->full());
    EXPECT_EQ(queue->size(), 0);
}

TEST_F(ThreadSafeQueueTest, SingleElementQueue) {
    queue->push(42);
    EXPECT_EQ(queue->size(), 1);
    EXPECT_FALSE(queue->empty());
    EXPECT_EQ(queue->front(), 42);
    EXPECT_EQ(queue->back(), 42);
    
    auto value = queue->pop();
    EXPECT_EQ(value, 42);
    EXPECT_TRUE(queue->empty());
}

TEST_F(ThreadSafeQueueTest, ZeroCapacityQueue) {
    ThreadSafeQueue<int> zeroCapacityQueue(0);
    EXPECT_FALSE(zeroCapacityQueue.full());
    EXPECT_TRUE(zeroCapacityQueue.push(1));
    
    EXPECT_TRUE(zeroCapacityQueue.push(1));
}

// ==================== 性能测试 ====================

TEST_F(ThreadSafeQueueTest, PerformanceTest) {
    const int numOperations = 1000; // 减少数量避免测试时间过长
    auto start = std::chrono::steady_clock::now();
    
    for (int i = 0; i < numOperations; ++i) {
        queue->push(i);
        auto value = queue->pop();
        EXPECT_EQ(value, i);
    }
    
    auto end = std::chrono::steady_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
    
    // 只是记录时间，不进行断言
    std::cout << "Single-threaded performance: " << duration.count() << "ms for " 
              << numOperations << " push/pop pairs" << std::endl;
}

int main(int argc, char **argv) {
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}